<?php
/*
#  This program outputs a QRcode as either a PNG, JPEG, or GIF.
#
#	Original version (C)2000-2009,Y.Swetake (version 0.50i)
#	From: http://www.venus.dti.ne.jp/~swe/program/qr_img0.50i.tar.gz
#	http://www.swetake.com/qr/
#	Licenced as "revised BSD License" by the original author
#		
#		Subsequent Changes
#	Copyright (c) 2012, Terence Eden
#	All rights reserved.
#	
#	Redistribution and use in source and binary forms, with or without
#	modification, are permitted provided that the following conditions are met:
#		* Redistributions of source code must retain the above copyright
#		  notices, this list of conditions and the following disclaimer.
#		* Redistributions in binary form must reproduce the above copyright
#		  notices, this list of conditions and the following disclaimer in the
#		  documentation and/or other materials provided with the distribution.
#		* Neither the name of the software nor the
#		  names of its contributors may be used to endorse or promote products
#		  derived from this software without specific prior written permission.
#	
#	THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
#	ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
#	WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
#	DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) BE LIABLE FOR ANY
#	DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
#	(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
#	LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
#	ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
#	(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
#	SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#		
#
#  This program outputs a QRcode as either a PNG, JPEG, or GIF. 
#
#  Supports QRcode version 1-40.
#
#  Requires PHP4.1 and gd 1.6 or higher.
#
#
# [usage]
#   qr.php?d=[data]&e=[(L,M,Q,H)]&s=[int]&v=[(1-40)]&t=[(J,G)]&size=[int]&download=[filename]
#			 (&m=[(1-16)]&n=[(2-16)](&p=[(0-255)],&o=[data]))
#
#   d		= data				URL encoded data.
#   e		= ECC level			L or M or Q or H   (default M)
#   s		= module size		(dafault PNG:4 JPEG:8)
#   v		= version			1-40 or Auto select if you do not set.
#   t		= image type		J: jpeg image, G: GIF image, default: PNG image
#   size	= image size		Integer. Specifies the width & height of the image. Default 400. Max 1480.
#   download = File name	URL encoded filename. If set, the content disposition will change to tell the browser to download the file.
#   raw  = rawurldecode the data. If set, the data in d will be URL decoded changing "%20" into " " etc.
#
#  structured append  m of n (experimental)
#   n= structure append n (2-16)
#   m= structure append m (1-16)
#   p= parity
#   o= original data (URL encoded data)  for calculating parity
#
#	The QR code standard is trademarked by Denso Wave, Inc.
#	http://www.denso-wave.com/qrcode/index-e.html
*/

//	Path to the data and image files
$path			= "./../data";		//	You must set path to data files.
$image_path	= "./../image";	//	You must set path to QRcode frame images.

//	Get the parameters
$qrcode_error_correct= strtolower($_GET["e"]);
$qrcode_module_size  = $_GET["s"];
$qrcode_version      = $_GET["v"];
$qrcode_raw          = $_GET["raw"];
$qrcode_image_type   = strtolower($_GET["t"]);
$qrcode_image_size   = $_GET["size"];
$qrcode_download     = $_GET["download"];

if ($qrcode_raw)
{
	$qrcode_data_string  = rawurldecode($_GET["d"]);
} else {
	$qrcode_data_string  = $_GET["d"];
}

//	Experimental Parameters
$qrcode_structureappend_n=@$_GET["n"];
$qrcode_structureappend_m=@$_GET["m"];
$qrcode_structureappend_parity=@$_GET["p"];
$qrcode_structureappend_originaldata=@$_GET["o"];


//	Set the Image Type
//	&t=
if ($qrcode_image_type == "j"){
	$qrcode_image_type = "jpeg";
}else if ($qrcode_image_type == "g"){
	$qrcode_image_type = "gif";
}else {
	$qrcode_image_type = "png";
}

//	Set the Module Size (this is *not* the same as the Image Size)
//	&s=
if ($qrcode_module_size > 0) {
} else {
	if ($qrcode_image_type == "jpeg"){
		$qrcode_module_size = 8;
	} else {
		$qrcode_module_size = 4;
	}
}

//	Set the Image Size (QR codes are square - so the height and width are the same)
//	&size=
if ($qrcode_image_size == null)	{
	$qrcode_image_size = 400;
}

//	Maximum Image Size
if ($qrcode_image_size > 1480)	{
  //	If you would prefer to display and error message, uncomment the following line
  //trigger_error("QRcode : Image width must be less than 1480 pixels",E_USER_ERROR);
  $qrcode_image_size = 1480;
}

//	If no data has been supplied
if (strlen($qrcode_data_string) <= 0) {
	trigger_error("QRcode : No data supplied.",E_USER_ERROR);
	exit;
}

//	Default Image Border
$mib = 0;

//	Create the image
$output_image = imagecreatetruecolor($qrcode_image_size, $qrcode_image_size);


//	Create the QR Code
$base_image = createQR();

//	Set the correct content header
Header("Content-type: image/".$qrcode_image_type);

//	Resize the QR Code 
imagecopyresized($output_image, $base_image, 0, 0, 0, 0, $qrcode_image_size, $qrcode_image_size, $mib, $mib);

if(file_exists($image_path.'/mask.png')){
	$mask = ImageCreateFromPNG($image_path.'/mask.png');
	$output_mask = imagecreate($qrcode_image_size, $qrcode_image_size);
	$w = imagesx( $mask );
    $h = imagesy( $mask );
	
	imagecopyresized($output_mask, $mask, 0, 0, 0, 0, $qrcode_image_size, $qrcode_image_size, $w, $h);
	
	imagecopy($output_image, $output_mask, 0, 0, 0, 0, $qrcode_image_size, $qrcode_image_size);
}

//	If the download parameter has been set, the content disposition must be changed to prompt the browser to download the image rather than display it
//	&download
if ($qrcode_download) {
	if ($qrcode_image_type == "jpeg"){
		$fileExtension = "jpg";
	} else if ($qrcode_image_type == "gif"){
		$fileExtension = "gif";
	} else {
		$fileExtension = "png";
	}
	header('Content-Disposition: attachment; filename="'.$qrcode_download.'.'.$fileExtension.'"');	
}

//	Send the image to the browser
if ($qrcode_image_type == "jpeg"){
	ImageJpeg($output_image);
} else if ($qrcode_image_type == "gif"){
	imagegif($output_image);
} else {
	ImagePng($output_image);
}

//	All done!
//	Clean up after ourselves!
imagedestroy($output_image);
imagedestroy($base_image);
exit;

//	Here be dragons!
//	Do not edit this code unless you are sure you understand what you are doing

function createQR()
{
	//	Global paramaters
	global	$qrcode_data_string, 
				$qrcode_error_correct, 
				$qrcode_module_size, 
				$qrcode_version, 
				$qrcode_image_type, 
				$qrcode_image_size, 
				$qrcode_structureappend_n, 
				$qrcode_structureappend_m, 
				$qrcode_structureappend_parity,
				$qrcode_structureappend_originaldata,
				$mib,
				$image_path,
				$path;

	//	This program supports an upper limit of version 40.
	//	Version 40 has 177 rows and 177 columns, and can encode up to 4,296 alphanumeric characters
	//	See http://code.google.com/apis/chart/infographics/docs/qr_codes.html
	$version_ul	= 40;
	
	
	//	Create the QR Code
	$data_length = strlen($qrcode_data_string);
	
	$data_counter = 0;
	if ($qrcode_structureappend_n>1
	 && $qrcode_structureappend_n<=16
	 && $qrcode_structureappend_m>0
	 && $qrcode_structureappend_m<=16){

		$data_value[0]=3;
		$data_bits[0]=4;

		$data_value[1]=$qrcode_structureappend_m-1;
		$data_bits[1]=4;

		$data_value[2]=$qrcode_structureappend_n-1;
		$data_bits[2]=4;


		$originaldata_length=strlen($qrcode_structureappend_originaldata);
		
		if ($originaldata_length>1){
			$qrcode_structureappend_parity=0;
			$i=0;
			while ($i<$originaldata_length){
				$qrcode_structureappend_parity=($qrcode_structureappend_parity ^ ord(substr($qrcode_structureappend_originaldata,$i,1)));
				$i++;
			}
		}

		$data_value[3]=$qrcode_structureappend_parity;
		$data_bits[3]=8;

		$data_counter=4;
	}

	$data_bits[$data_counter]=4;

	/*  --- determine encode mode */

	if (preg_match("/[^0-9]/",$qrcode_data_string)!=0){
		if (preg_match("/[^0-9A-Z \$\*\%\+\.\/\:\-]/",$qrcode_data_string)!=0) {


		 /*  --- 8bit byte mode */

			$codeword_num_plus = array(	0,0,0,0,0,0,0,0,0,0,
													8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,
													8,8,8,8,8,8,8,8,8,8,8,8,8,8);

			$data_value[$data_counter]=4;
			$data_counter++;
			$data_value[$data_counter]=$data_length;
			$data_bits[$data_counter]=8;   /* #version 1-9 */
			$codeword_num_counter_value=$data_counter;

			$data_counter++;
			$i=0;
			while ($i<$data_length){
				$data_value[$data_counter]=ord(substr($qrcode_data_string,$i,1));
				$data_bits[$data_counter]=8;
				$data_counter++;
				$i++;
			}
		} else {

		/* ---- alphanumeric mode */

			$codeword_num_plus = array(0,0,0,0,0,0,0,0,0,0,
												2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,
												4,4,4,4,4,4,4,4,4,4,4,4,4,4);

			$data_value[$data_counter]=2;
			$data_counter++;
			$data_value[$data_counter]=$data_length;
			$data_bits[$data_counter]=9;  /* #version 1-9 */
			$codeword_num_counter_value=$data_counter;


			$alphanumeric_character_hash = array(
														"0"=>0,"1"=>1,"2"=>2,"3"=>3,"4"=>4,
														"5"=>5,"6"=>6,"7"=>7,"8"=>8,"9"=>9,
														"A"=>10,"B"=>11,"C"=>12,"D"=>13,"E"=>14,
														"F"=>15,"G"=>16,"H"=>17,"I"=>18,"J"=>19,
														"K"=>20,"L"=>21,"M"=>22,"N"=>23,"O"=>24,
														"P"=>25,"Q"=>26,"R"=>27,"S"=>28,"T"=>29,
														"U"=>30,"V"=>31,"W"=>32,"X"=>33,"Y"=>34,
														"Z"=>35," "=>36,"$"=>37,"%"=>38,"*"=>39,
														"+"=>40,"-"=>41,"."=>42,"/"=>43,":"=>44);

			$i=0;
			$data_counter++;
			while ($i<$data_length){
				if (($i %2)==0){
					$data_value[$data_counter]=$alphanumeric_character_hash[substr($qrcode_data_string,$i,1)];
					$data_bits[$data_counter]=6;
				} else {
					$data_value[$data_counter]=$data_value[$data_counter]*45+$alphanumeric_character_hash[substr($qrcode_data_string,$i,1)];
					$data_bits[$data_counter]=11;
					$data_counter++;
				}
				$i++;
			}
		}
	} else {

		/* ---- numeric mode */

		$codeword_num_plus = array (	0,0,0,0,0,0,0,0,0,0,
												2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,
												4,4,4,4,4,4,4,4,4,4,4,4,4,4);

		$data_value[$data_counter]=1;
		$data_counter++;
		$data_value[$data_counter]=$data_length;
		$data_bits[$data_counter]=10;   /* #version 1-9 */
		$codeword_num_counter_value=$data_counter;

		$i=0;
		$data_counter++;
		while ($i<$data_length){
			if (($i % 3)==0){
				$data_value[$data_counter]=substr($qrcode_data_string,$i,1);
				$data_bits[$data_counter]=4;
			} else {
				 $data_value[$data_counter]=$data_value[$data_counter]*10+substr($qrcode_data_string,$i,1);
			 if (($i % 3)==1){
				 $data_bits[$data_counter]=7;
			 } else {
				 $data_bits[$data_counter]=10;
				 $data_counter++;
			 }
			}
			$i++;
		}
	}
	if (@$data_bits[$data_counter]>0) {
		$data_counter++;
	}
	$i=0;
	$total_data_bits=0;
	while($i<$data_counter){
		$total_data_bits+=$data_bits[$i];
		$i++;
	}

	//	Error Correction
	$ecc_character_hash = array (
									"l"=>"1",
									"m"=>"0",
									"q"=>"3",
									"h"=>"2");

	$ec=@$ecc_character_hash[$qrcode_error_correct]; 

	if (!$ec){$ec=0;}

	$max_data_bits_array=array(
									0,128,224,352,512,688,864,992,1232,1456,1728,
									2032,2320,2672,2920,3320,3624,4056,4504,5016,5352,
									5712,6256,6880,7312,8000,8496,9024,9544,10136,10984,
									11640,12328,13048,13800,14496,15312,15936,16816,17728,18672,

									152,272,440,640,864,1088,1248,1552,1856,2192,
									2592,2960,3424,3688,4184,4712,5176,5768,6360,6888,
									7456,8048,8752,9392,10208,10960,11744,12248,13048,13880,
									14744,15640,16568,17528,18448,19472,20528,21616,22496,23648,

									72,128,208,288,368,480,528,688,800,976,
									1120,1264,1440,1576,1784,2024,2264,2504,2728,3080,
									3248,3536,3712,4112,4304,4768,5024,5288,5608,5960,
									6344,6760,7208,7688,7888,8432,8768,9136,9776,10208,

									104,176,272,384,496,608,704,880,1056,1232,
									1440,1648,1952,2088,2360,2600,2936,3176,3560,3880,
									4096,4544,4912,5312,5744,6032,6464,6968,7288,7880,
									8264,8920,9368,9848,10288,10832,11408,12016,12656,13328
								);

	//	Which version of the QR code do we need to generate?
	//	If the user hasn't specified a version, autogenenerate one.
	if (!is_numeric($qrcode_version)){
		$qrcode_version=0;
	}
	if (!$qrcode_version){
		/* #--- auto version select */
		$i=1+40*$ec;
		$j=$i+39;
		$qrcode_version=1; 
		while ($i<=$j){
			if (($max_data_bits_array[$i])>=$total_data_bits+$codeword_num_plus[$qrcode_version]	 ){
				$max_data_bits=$max_data_bits_array[$i];
				break;
			}
		 $i++;
		 $qrcode_version++;
		}
	} else {
		 $max_data_bits=$max_data_bits_array[$qrcode_version+40*$ec];
	}
	if ($qrcode_version>$version_ul){
	  trigger_error("QRcode : too large version.",E_USER_ERROR);
	}

	$total_data_bits+=$codeword_num_plus[$qrcode_version];
		$data_bits[$codeword_num_counter_value]+=$codeword_num_plus[$qrcode_version];

	$max_codewords_array=array(
									0,26,44,70,100,134,172,196,242,
									292,346,404,466,532,581,655,733,815,901,991,1085,1156,
									1258,1364,1474,1588,1706,1828,1921,2051,2185,2323,2465,
									2611,2761,2876,3034,3196,3362,3532,3706);

	$max_codewords=$max_codewords_array[$qrcode_version];
	$max_modules_1side=17+($qrcode_version <<2);

	$matrix_remain_bit=array(
								0,0,7,7,7,7,7,0,0,0,0,0,0,0,3,3,3,3,3,3,3,
								4,4,4,4,4,4,4,3,3,3,3,3,3,3,0,0,0,0,0,0);

	/* ---- read version ECC data file */

	$byte_num=$matrix_remain_bit[$qrcode_version]+($max_codewords << 3);
	$filename=$path."/qrv".$qrcode_version."_".$ec.".dat";
	$fp1 = fopen ($filename, "rb");
		$matx=fread($fp1,$byte_num);
		$maty=fread($fp1,$byte_num);
		$masks=fread($fp1,$byte_num);
		$fi_x=fread($fp1,15);
		$fi_y=fread($fp1,15);
		$rs_ecc_codewords=ord(fread($fp1,1));
		$rso=fread($fp1,128);
	fclose($fp1);

	$matrix_x_array=unpack("C*",$matx);
	$matrix_y_array=unpack("C*",$maty);
	$mask_array=unpack("C*",$masks);

	$rs_block_order=unpack("C*",$rso);

	$format_information_x2=unpack("C*",$fi_x);
	$format_information_y2=unpack("C*",$fi_y);

	$format_information_x1=array(0,1,2,3,4,5,7,8,8,8,8,8,8,8,8);
	$format_information_y1=array(8,8,8,8,8,8,8,8,7,5,4,3,2,1,0);

	$max_data_codewords=($max_data_bits >>3);

	$filename = $path."/rsc".$rs_ecc_codewords.".dat";
	$fp0 = fopen ($filename, "rb");
	$i=0;
	while ($i<256) {
		$rs_cal_table_array[$i]=fread ($fp0,$rs_ecc_codewords);
		$i++;
	}
	fclose ($fp0);

	/*  --- set terminator */

	if ($total_data_bits<=$max_data_bits-4){
		$data_value[$data_counter]=0;
		$data_bits[$data_counter]=4;
	} else {
		if ($total_data_bits<$max_data_bits){
		$data_value[$data_counter]=0;
			$data_bits[$data_counter]=$max_data_bits-$total_data_bits;
		} else {
			if ($total_data_bits>$max_data_bits){
			trigger_error("QRcode : Overflow error",E_USER_ERROR);
			exit;
			}
		}
	}

	/* ----divide data by 8bit */

	$i=0;
	$codewords_counter=0;
	$codewords[0]=0;
	$remaining_bits=8;

	while ($i<=$data_counter) {
		$buffer=@$data_value[$i];
		$buffer_bits=@$data_bits[$i];

		$flag=1;
		while ($flag) {
			if ($remaining_bits>$buffer_bits){  
				$codewords[$codewords_counter]=((@$codewords[$codewords_counter]<<$buffer_bits) | $buffer);
				$remaining_bits-=$buffer_bits;
				$flag=0;
			} else {
				$buffer_bits-=$remaining_bits;
				$codewords[$codewords_counter]=(($codewords[$codewords_counter] << $remaining_bits) | ($buffer >> $buffer_bits));

				if ($buffer_bits==0) {
					$flag=0;
				} else {
					$buffer= ($buffer & ((1 << $buffer_bits)-1) );
					$flag=1;   
				}

				$codewords_counter++;
				if ($codewords_counter<$max_data_codewords-1){
					$codewords[$codewords_counter]=0;
				}
				$remaining_bits=8;
			}
		}
		$i++;
	}
	if ($remaining_bits!=8) {
		$codewords[$codewords_counter]=$codewords[$codewords_counter] << $remaining_bits;
	} else {
		$codewords_counter--;
	}

	/* ----  set padding character */

	if ($codewords_counter<$max_data_codewords-1){
		$flag=1;
		while ($codewords_counter<$max_data_codewords-1){
			$codewords_counter++;
			if ($flag==1) {
				$codewords[$codewords_counter]=236;
			} else {
				$codewords[$codewords_counter]=17;
			}
			$flag=$flag*(-1);
		}
	}

	/* ---- RS-ECC prepare */

	$i=0;
	$j=0;
	$rs_block_number=0;
	$rs_temp[0]="";

	while($i<$max_data_codewords){

		$rs_temp[$rs_block_number].=chr($codewords[$i]);
		$j++;

		if ($j>=$rs_block_order[$rs_block_number+1]-$rs_ecc_codewords){
			$j=0;
			$rs_block_number++;
			$rs_temp[$rs_block_number]="";
		}
		$i++;
	}


	/*
	#
	# RS-ECC main
	#
	*/

	$rs_block_number=0;
	$rs_block_order_num=count($rs_block_order);

	while ($rs_block_number<$rs_block_order_num){

		$rs_codewords=$rs_block_order[$rs_block_number+1];
		$rs_data_codewords=$rs_codewords-$rs_ecc_codewords;

		$rstemp=$rs_temp[$rs_block_number].str_repeat(chr(0),$rs_ecc_codewords);
		$padding_data=str_repeat(chr(0),$rs_data_codewords);

		$j=$rs_data_codewords;
		while($j>0){
			$first=ord(substr($rstemp,0,1));

			if ($first){
				$left_chr=substr($rstemp,1);
				$cal=$rs_cal_table_array[$first].$padding_data;
				$rstemp=$left_chr ^ $cal;
			} else {
				$rstemp=substr($rstemp,1);
			}

			$j--;
		}

		$codewords=array_merge($codewords,unpack("C*",$rstemp));

		$rs_block_number++;
	}

	/* ---- flash matrix */

	$i=0;
	while ($i<$max_modules_1side){
		$j=0;
		while ($j<$max_modules_1side){
			$matrix_content[$j][$i]=0;
			$j++;
		}
		$i++;
	}

	/* --- attach data */

	$i=0;
	while ($i<$max_codewords){
		$codeword_i=$codewords[$i];
		$j=8;
		while ($j>=1){
			$codeword_bits_number=($i << 3) +  $j;
			$matrix_content[ $matrix_x_array[$codeword_bits_number] ][ $matrix_y_array[$codeword_bits_number] ]=((255*($codeword_i & 1)) ^ $mask_array[$codeword_bits_number] ); 
			$codeword_i= $codeword_i >> 1;
			$j--;
		}
		$i++;
	}

	$matrix_remain=$matrix_remain_bit[$qrcode_version];
	while ($matrix_remain){
		$remain_bit_temp = $matrix_remain + ( $max_codewords <<3);
		$matrix_content[ $matrix_x_array[$remain_bit_temp] ][ $matrix_y_array[$remain_bit_temp] ]  =  ( 255 ^ $mask_array[$remain_bit_temp] );
		$matrix_remain--;
	}

	#--- mask select

	$min_demerit_score=0;
		$hor_master="";
		$ver_master="";
		$k=0;
		while($k<$max_modules_1side){
			$l=0;
			while($l<$max_modules_1side){
				$hor_master=$hor_master.chr($matrix_content[$l][$k]);
				$ver_master=$ver_master.chr($matrix_content[$k][$l]);
				$l++;
			}
			$k++;
		}
	$i=0;
	$all_matrix=$max_modules_1side * $max_modules_1side; 
	while ($i<8){
		$demerit_n1=0;
		$ptn_temp=array();
		$bit= 1<< $i;
		$bit_r=(~$bit)&255;
		$bit_mask=str_repeat(chr($bit),$all_matrix);
		$hor = $hor_master & $bit_mask;
		$ver = $ver_master & $bit_mask;

		$ver_shift1=$ver.str_repeat(chr(170),$max_modules_1side);
		$ver_shift2=str_repeat(chr(170),$max_modules_1side).$ver;
		$ver_shift1_0=$ver.str_repeat(chr(0),$max_modules_1side);
		$ver_shift2_0=str_repeat(chr(0),$max_modules_1side).$ver;
		$ver_or=chunk_split(~($ver_shift1 | $ver_shift2),$max_modules_1side,chr(170));
		$ver_and=chunk_split(~($ver_shift1_0 & $ver_shift2_0),$max_modules_1side,chr(170));

		$hor=chunk_split(~$hor,$max_modules_1side,chr(170));
		$ver=chunk_split(~$ver,$max_modules_1side,chr(170));
		$hor=$hor.chr(170).$ver;

		$n1_search="/".str_repeat(chr(255),5)."+|".str_repeat(chr($bit_r),5)."+/";
		$n3_search=chr($bit_r).chr(255).chr($bit_r).chr($bit_r).chr($bit_r).chr(255).chr($bit_r);

		$demerit_n3=substr_count($hor,$n3_search)*40;
		$demerit_n4=floor(abs(( (100* (substr_count($ver,chr($bit_r))/($byte_num)) )-50)/5))*10;


		$n2_search1="/".chr($bit_r).chr($bit_r)."+/";
		$n2_search2="/".chr(255).chr(255)."+/";
		$demerit_n2=0;
		preg_match_all($n2_search1,$ver_and,$ptn_temp);
		foreach($ptn_temp[0] as $str_temp){
			$demerit_n2+=(strlen($str_temp)-1);
		}
		$ptn_temp=array();
		preg_match_all($n2_search2,$ver_or,$ptn_temp);
		foreach($ptn_temp[0] as $str_temp){
			$demerit_n2+=(strlen($str_temp)-1);
		}
		$demerit_n2*=3;
	  
		$ptn_temp=array();

		preg_match_all($n1_search,$hor,$ptn_temp);
		foreach($ptn_temp[0] as $str_temp){
			$demerit_n1+=(strlen($str_temp)-2);
		}

		$demerit_score=$demerit_n1+$demerit_n2+$demerit_n3+$demerit_n4;

		if ($demerit_score<=$min_demerit_score || $i==0){
			$mask_number=$i;
			$min_demerit_score=$demerit_score;
		}

	$i++;
	}

	$mask_content=1 << $mask_number;

	# --- format information

	$format_information_value=(($ec << 3) | $mask_number);
	$format_information_array=array("101010000010010","101000100100101",
	"101111001111100","101101101001011","100010111111001","100000011001110",
	"100111110010111","100101010100000","111011111000100","111001011110011",
	"111110110101010","111100010011101","110011000101111","110001100011000",
	"110110001000001","110100101110110","001011010001001","001001110111110",
	"001110011100111","001100111010000","000011101100010","000001001010101",
	"000110100001100","000100000111011","011010101011111","011000001101000",
	"011111100110001","011101000000110","010010010110100","010000110000011",
	"010111011011010","010101111101101");
	$i=0;
	while ($i<15){
		$content=substr($format_information_array[$format_information_value],$i,1);

		$matrix_content[$format_information_x1[$i]][$format_information_y1[$i]]=$content * 255;
		$matrix_content[$format_information_x2[$i+1]][$format_information_y2[$i+1]]=$content * 255;
		$i++;
	}


	$mib=$max_modules_1side+8;

	$output_image =ImageCreate($qrcode_image_size,$qrcode_image_size);

	$image=$image_path."/qrv".$qrcode_version.".png";

	$base_image=ImageCreateFromPNG($image);

	$col[1]=ImageColorAllocate($base_image,0,0,0);
	$col[0]=ImageColorAllocate($base_image,255,255,255);

	$i=4;
	$mxe=4+$max_modules_1side;
	$ii=0;
	while ($i<$mxe){
		$j=4;
		$jj=0;
		while ($j<$mxe){
			if ($matrix_content[$ii][$jj] & $mask_content){
				ImageSetPixel($base_image,$i,$j,$col[1]); 
			}
			$j++;
			$jj++;
		}
		$i++;
		$ii++;
	}
	
	////
	//Edit Nick
	//
	//Masking image code goes here.
	////
	/*$mask = ImageCreateFromPNG($image_path.'/mask.png');
	imagealphablending($mask, true);
	imagesavealpha($mask, true);
	imagealphablending($base_image, true);
	imagesavealpha($base_image, true);
	imagecopy($base_image, $mask, 0, 0, 0, 0, 100, 100);*/

	return $base_image;
}

// A fix to get a function like imagecopymerge WITH ALPHA SUPPORT
// Main script by aiden dot mail at freemail dot hu
// Transformed to imagecopymerge_alpha() by rodrigo dot polo at gmail dot com
function imagecopymerge_alpha($dst_im, $src_im, $dst_x, $dst_y, $src_x, $src_y, $src_w, $src_h, $pct){
    if(!isset($pct)){
        return false;
    }
    $pct /= 100;
    // Get image width and height
    $w = imagesx( $src_im );
    $h = imagesy( $src_im );
    // Turn alpha blending off
    imagealphablending( $src_im, false );
    // Find the most opaque pixel in the image (the one with the smallest alpha value)
    $minalpha = 127;
    for( $x = 0; $x < $w; $x++ )
    for( $y = 0; $y < $h; $y++ ){
        $alpha = ( imagecolorat( $src_im, $x, $y ) >> 24 ) & 0xFF;
        if( $alpha < $minalpha ){
            $minalpha = $alpha;
        }
    }
    //loop through image pixels and modify alpha for each
    for( $x = 0; $x < $w; $x++ ){
        for( $y = 0; $y < $h; $y++ ){
            //get current alpha value (represents the TANSPARENCY!)
            $colorxy = imagecolorat( $src_im, $x, $y );
            $alpha = ( $colorxy >> 24 ) & 0xFF;
            //calculate new alpha
            if( $minalpha !== 127 ){
                $alpha = 127 + 127 * $pct * ( $alpha - 127 ) / ( 127 - $minalpha );
            } else {
                $alpha += 127 * $pct;
            }
            //get the color index with new alpha
            $alphacolorxy = imagecolorallocatealpha( $src_im, ( $colorxy >> 16 ) & 0xFF, ( $colorxy >> 8 ) & 0xFF, $colorxy & 0xFF, $alpha );
            //set pixel with the new color + opacity
            if( !imagesetpixel( $src_im, $x, $y, $alphacolorxy ) ){
                return false;
            }
        }
    }
    // The image copy
    imagecopy($dst_im, $src_im, $dst_x, $dst_y, $src_x, $src_y, $src_w, $src_h);
} 
